using System;
using System.Threading;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace Derrick.Web
{
    abstract public class Server
    {
        protected Thread _listenerThread = null;
		private TcpListener listener = null;
        private AuthConfig authconfig;
        protected TraceSwitch _traceSwitch;
        protected List<Client> clients = new List<Client>();
        protected volatile object _lockObj = new object();


		public Server(IPAddress ip, Int32 port, AuthConfig a)
		{


            try
            {
                _traceSwitch = new TraceSwitch("TraceLevelSwitch", "Comet Tracing");
                
                authconfig = a;



                //listener = new TcpListener(port);
                listener = new TcpListener(ip, port);
                listener.ExclusiveAddressUse = true;
                listener.Start();

                _listenerThread = new Thread(new ThreadStart(Loop));
                _listenerThread.Start();


            }
            catch (Exception ex)
            {
                //EventLog.WriteEntry("MetroLinx COMET", ex.ToString(), EventLogEntryType.Error);
                Trace.WriteLineIf(_traceSwitch.TraceError, "Error starting on port " + port + ": " + ex.ToString(), "COMET Server");
            }

		}
				
		private void Loop()
		{
            try
            {
                //List<Client> clients = new List<Client>();

                while (true)
                {
                    TcpClient client = listener.AcceptTcpClient();
                    Trace.WriteLineIf(_traceSwitch.TraceInfo, "TCP client accepted.", "COMET Server");
                    bool addClientFlag = true;

                    Client dc = new Client(client, this, authconfig);
                    foreach (Client currentClient in clients)
                    {
                        if (dc.TCPClient == currentClient.TCPClient)
                        {
                            lock (_lockObj)
                            {
                                addClientFlag = false;
                            }
                        }

                    }

                    if (addClientFlag)
                    {
                        lock (_lockObj)
                        {
                            clients.Add(dc);
                        }
                    }

                    Trace.WriteLineIf(_traceSwitch.TraceInfo, "Number of TCP clients: " + clients.Count);

                    int i = 0;
                    while (i < clients.Count)
                    {
                        if (!clients[i].IsLive)
                        {
                            clients.RemoveAt(i);
                        }
                        i++;
                    }
                }
            }
            catch (Exception ex)
            {
                //EventLog.WriteEntry("MetroLinx COMET", ex.ToString(), EventLogEntryType.Error);
                Trace.WriteLineIf(_traceSwitch.TraceError, ex.ToString(), "COMET Server");
            }
		}

		
		public bool IsRunning()
		{
			return _listenerThread.IsAlive;
		}



        public void CloseListener()
        {
            if (listener != null)
            {
                listener.Stop();
            }
        }

        abstract public Response HandleRequest(Request request, DateTime lastUpdate);


    }
}
